package com.seed.bpmn.rest;

import com.seed.bpmn.engine.IBPMNRepositoryService;
import com.seed.bpmn.engine.common.util.Empty;
import com.seed.bpmn.engine.common.util.Page;
import com.seed.bpmn.engine.common.util.ResultData;
import com.seed.bpmn.engine.dto.FlowDTO;
import com.seed.bpmn.engine.dto.NodeDTO;
import com.seed.bpmn.engine.dto.ProcessDefinitionDTO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import net.sf.json.JSON;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;

@Api(description = "流程定义操作接口")
@Controller
@RequestMapping("/bpmn/repository")
public class RepositoryController {

    @Resource(name = "bpmnRepositoryService")
    private IBPMNRepositoryService repositoryService;

    @ApiOperation(value = "部署流程图接口")
    @RequestMapping(value="/deploy", method = RequestMethod.POST, consumes = "multipart/form-data")
    @ResponseBody
    public JSON deploy(HttpServletRequest request, MultipartFile file){
        ResultData data = new ResultData();
        try {
            String name = request.getParameter("name");
            InputStream is = file.getInputStream();
            String fileName = file.getOriginalFilename();

            ProcessDefinitionDTO d = repositoryService.deploy(name, fileName, "", is);

            if(Empty.isNotEmpty(d)){
                data = ResultData.success("操作成功！",d);
            }else{
                data = ResultData.failure("操作失败！");
            }
        } catch (Exception e) {
            data = ResultData.failure("操作失败！"+e.getMessage());
        }
        return data.toJson();
    }

    @ApiOperation(value = "根据流程定义id获取流程定义")
    @RequestMapping(value="/process-definition-id/{id}", method = RequestMethod.GET)
    @ResponseBody
    public JSON getProcessDefinition(@PathVariable String id) {
        ResultData data = new ResultData();
        try {
            ProcessDefinitionDTO d = repositoryService.getProcessDefinition(id);

            if(Empty.isNotEmpty(d)){
                data = ResultData.success("操作成功！",d);
            }else{
                data = ResultData.failure("操作失败！");
            }
        } catch (Exception e) {
            data = ResultData.failure("操作失败！"+e.getMessage());
        }
        return data.toJson();
    }

    @ApiOperation(value = "分页获取流程定义")
    @RequestMapping(value="/process-definition/page", method = RequestMethod.POST)
    @ResponseBody
    public JSON findProcessDefinitionByPage(HttpServletRequest request) {
        ResultData data = new ResultData();
        try {
            //任务id
            String name = request.getParameter("name");
            //流程定义key
            String key = request.getParameter("key");
            String pageSize = request.getParameter("pageSize");
            String pageIndex = request.getParameter("pageIndex");

            //分页对象设置
            Page page = new Page();
            int size = Integer.parseInt(pageSize);
            int index = Integer.parseInt(pageIndex);
            page.setPageSize(size);
            page.setPageIndex(index);

            List<ProcessDefinitionDTO> list = this.repositoryService.findProcessDefinitionByPage(name, key, page);

            Map<String,Object> map = new HashMap<String,Object>();
            map.put("items",list);
            map.put("totalPages",page.getTotalPages());
            map.put("pageIndex",page.getPageIndex());
            map.put("totalObjects",page.getTotalObjects());

            data = ResultData.success("操作成功！",map);
        } catch (Exception e) {
            data = ResultData.failure("操作失败！"+e.getMessage());
        }
        return data.toJson();
    }

    @ApiOperation(value = "根据流程定义key获取流程定义")
    @RequestMapping(value="/process-definition-key/{key}", method = RequestMethod.GET)
    @ResponseBody
    public JSON findProcessDefinitionByKey(@PathVariable String key){
        ResultData data = new ResultData();
        try {
            ProcessDefinitionDTO d = repositoryService.findProcessDefinitionByKey(key);

            if(Empty.isNotEmpty(d)){
                data = ResultData.success("操作成功！",d);
            }else{
                data = ResultData.failure("操作失败！");
            }
        } catch (Exception e) {
            data = ResultData.failure("操作失败！"+e.getMessage());
        }
        return data.toJson();
    }

    @ApiOperation(value = "根据流程定义key、流程环节id获取流程节点信息")
    @RequestMapping(value="/node/process-definition-key", method = RequestMethod.POST)
    @ResponseBody
    public JSON getNodeByProcessDefinitionKey(HttpServletRequest request){
        ResultData data = new ResultData();
        try {
            String key = request.getParameter("key");
            String nodeId = request.getParameter("nodeId");

            NodeDTO d = repositoryService.getNodeByProcessDefinitionKey(key, nodeId);

            if(Empty.isNotEmpty(d)){
                data = ResultData.success("操作成功！",d);
            }else{
                data = ResultData.failure("操作失败！");
            }
        } catch (Exception e) {
            data = ResultData.failure("操作失败！"+e.getMessage());
        }
        return data.toJson();
    }

    @ApiOperation(value = "根据流程定义id获取该流程定义所有流程节点信息")
    @RequestMapping(value="/node/{processDefinitionId}", method = RequestMethod.GET)
    @ResponseBody
    public JSON getNodeByProcessDefinitionId(@PathVariable String processDefinitionId){
        ResultData data = new ResultData();
        try {
            List<NodeDTO> list = repositoryService.getNodeByProcessDefinitionId(processDefinitionId);
            if(Empty.isNotEmpty(list)){
                data = ResultData.success("操作成功！",list);
            }else{
                data = ResultData.failure("操作失败！");
            }
        } catch (Exception e) {
            data = ResultData.failure("操作失败！"+e.getMessage());
        }
        return data.toJson();
    }

    @ApiOperation(value = "根据流程定义id、流程环节id获取流程节点信息")
    @RequestMapping(value="/node/process-definition-id/{id}/{nodeId}", method = RequestMethod.GET)
    @ResponseBody
    public JSON getNodeByProcessDefinitionId(@PathVariable String id, @PathVariable String nodeId) {
        ResultData data = new ResultData();
        try {
            NodeDTO d = repositoryService.getNodeByProcessDefinitionId(id, nodeId);
            if(Empty.isNotEmpty(d)){
                data = ResultData.success("操作成功！",d);
            }else{
                data = ResultData.failure("操作失败！");
            }
        } catch (Exception e) {
            data = ResultData.failure("操作失败！"+e.getMessage());
        }
        return data.toJson();
    }

    @ApiOperation(value = "获取某个流程任务所在流程节点信息")
    @RequestMapping(value="/node/task/{id}", method = RequestMethod.GET)
    @ResponseBody
    public JSON getNodeByTaskId(@PathVariable String id) {
        ResultData data = new ResultData();
        try {
            NodeDTO d = repositoryService.getNodeByTaskId(id);
            if(Empty.isNotEmpty(d)){
                data = ResultData.success("操作成功！",d);
            }else{
                data = ResultData.failure("操作失败！");
            }
        } catch (Exception e) {
            data = ResultData.failure("操作失败！"+e.getMessage());
        }
        return data.toJson();
    }

    @ApiOperation(value = "获取下一流转环节信息")
    @RequestMapping(value="/next/transitions", method = RequestMethod.GET)
    @ResponseBody
    public JSON getNextTransitions(HttpServletRequest request) {
        ResultData data = new ResultData();
        try {
            //任务id
            String taskId = request.getParameter("taskId");

            //流程定义id
            String processDefinitionId = request.getParameter("processDefinitionId");

            //当前环节id
            String nodeId = request.getParameter("nodeId");

            List<FlowDTO> d = new ArrayList<>();

            if(Empty.isNotEmpty(taskId)){
                d = repositoryService.getNextTransitions(null, taskId);
            }else if(Empty.isNotEmpty(nodeId)){
                d = repositoryService.getNextTransitions(processDefinitionId, taskId, nodeId);
            }else{
                d = repositoryService.getNextTransitions(processDefinitionId, null);
            }

            if(Empty.isNotEmpty(d)){
                data = ResultData.success("操作成功！",d);
            }else{
                data = ResultData.failure("操作失败！");
            }
        } catch (Exception e) {
            data = ResultData.failure("操作失败！"+e.getMessage());
        }
        return data.toJson();
    }

    @ApiOperation(value = "根据流程定义id获取流程定义（模版）资源")
    @RequestMapping(value="/resource/process-definition/{id}/type/{type}", method = RequestMethod.GET)
    @ResponseBody
    public void getProcessDefinitionResource(@PathVariable String id, @PathVariable String type, HttpServletResponse response){
        if(Empty.isNotEmpty(id)){
            try {
                InputStream is = repositoryService.getProcessDefinitionById(id,type);
                writerResponse(response,is,type);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @ApiOperation(value = "根据流程实例id获取流程定义（模版）资源")
    @RequestMapping(value="/resource/process-instance/{id}/type/{type}", method = RequestMethod.GET)
    @ResponseBody
    public void getProcessDefinitionByProcessInstanceId(@PathVariable String id, @PathVariable String type, HttpServletResponse response) {
        if(Empty.isNotEmpty(id)){
            try {
                InputStream is = repositoryService.getProcessDefinitionByProcessInstanceId(id,type);
                writerResponse(response,is,type);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void writerResponse(HttpServletResponse response,InputStream is,String type) throws Exception{
        if(!Empty.isEmpty(is)){
            response.setCharacterEncoding("UTF-8");
            if("image".equalsIgnoreCase(type)){
                response.setContentType("image/png");
            }else{
                response.setContentType("text/xml");
            }

            OutputStream os = response.getOutputStream();
            byte[] buffer = new byte[is.available()];
            is.read(buffer);
            os.write(buffer);
            os.flush();
            os.close();
            response.flushBuffer();
            is.close();
        }
    }

    @ApiOperation(value = "流程删除流程定义（模版）")
    @RequestMapping(value="/process-definition/delete", method = RequestMethod.POST)
    @ResponseBody
    public JSON deleteProcessDefinition(HttpServletRequest request) throws Exception {
        ResultData data = new ResultData();
        try{
            String[] ids = request.getParameterValues("id");
            this.repositoryService.deleteProcessDefinition(Arrays.asList(ids));
            data = ResultData.success("操作成功！");
        } catch (Exception e) {
            data = ResultData.failure("操作失败！"+e.getMessage());
        }
        return data.toJson();
    }

    @ApiOperation(value = "激活与挂起流程定义（模版）")
    @RequestMapping(value="/process-definition/update", method = RequestMethod.POST)
    @ResponseBody
    public JSON updateProcessDefinition(HttpServletRequest request) throws Exception {
        ResultData data = new ResultData();
        try{
            String[] ids = request.getParameterValues("id");
            String type = request.getParameter("type");
            int t = Integer.parseInt(type);
            this.repositoryService.updateProcessDefinition(Arrays.asList(ids),t);
            data = ResultData.success("操作成功！");
        } catch (Exception e) {
            data = ResultData.failure("操作失败！"+e.getMessage());
        }
        return data.toJson();

    }
}
